home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!ucsd!ames!necntc!ncoast!allbery
- From: bill@qst1.tcc.com (Bill Cox)
- Newsgroups: comp.sources.misc
- Subject: v03i077: hold -- terminate a pipe with its input
- Message-ID: <8807050034.AA23702@ccicpg>
- Date: 3 Jul 88 21:04:10 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: bill@qst1.tcc.com (Bill Cox)
- Lines: 209
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 3, Issue 77
- Submitted-by: "Bill Cox" <bill@qst1.tcc.com>
- Archive-name: hold2
-
- [Is my memory going? I don't remember seeing a first version of this. ++bsa]
-
- Here's an unpdated version of hold.c, that lets you terminate a pipe with its
- input file, effectively putting the output back into the input file, as in
- tail SYSLOG | hold SYSLOG
- This version contains some fixes noticed by readers at ncoast.
-
- To build it, simply
- cc -O -o hold hold.c
- It's been compiled and run under V7, SYSV, XENIX and MS-DOS in its present
- form.
-
- Questions/bugs/flames to Bill Cox, (714)631-4452 (voice)
- or uunet!ccicpg!qst1!bill
-
- RATIONALE: Why use hold?
-
- Let's say you have the file tmp, which contains:
- AA#AAAA
- BBBB#BB
-
- And you wish to change the '#'s to '~'s. If you
- simply say sed 's/#/~/' tmp, you see
- AA~AAAA
- BBBB~BB
- just as you would expect.
-
- Now, enter sed 's/#/~/' tmp > tmp (in effect asking the shell to
- over-write the input file with the output) then cat tmp. Surprise,
- tmp is a null file!
-
- Now, enter sed 's/#/~/' tmp | hold tmp; cat tmp
- AA~AAAA
- BBBB~BB
- Just as you expect. Because hold creates a temporary file FOR YOU,
- which doesn't appear as an output on the command line.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: hold.c
- # Wrapped by srcs@qst1 on Mon Jul 4 17:21:31 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'hold.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'hold.c'\"
- else
- echo shar: Extracting \"'hold.c'\" \(2960 characters\)
- sed "s/^X//" >'hold.c' <<'END_OF_FILE'
- X/*
- X * hold terminate a pipe, gather stdin into a temporary,
- X * then rename the temporary to the argument's name.
- X *
- X * Example: ... | hold filename
- X * or: ... | hold > filename
- X *
- X */
- X
- X#ifdef MSDOS
- X#include <io.h>
- X#endif
- X
- X#include <stdio.h>
- X#include <errno.h>
- X#ifndef MSDOS
- X#include <signal.h>
- X#endif
- XFILE *fp = NULL;
- Xint stdoutf;
- X
- X#ifdef MSDOS
- Xchar fname[11] = "holdXXXXXX";
- X#endif
- X#ifdef M_XENIX
- Xchar fname[11] = "holdXXXXXX";
- X#else
- Xchar fname[20] = "/usr/tmp/holdXXXXXX";
- X#endif
- X
- X
- Xextern int errno; /* Declare global error value. */
- X
- X#ifndef MSDOS
- X/* This routine gains control when a signal is trapped. It unlinks the
- X * temporary file. This is necessary when a pipe gets broken.
- X */
- Xint Trap()
- X{
- Xunlink(fname); /* Ignore errors at this point, we are dead anyway. */
- Xexit(1);
- X}
- X#endif
- X
- Xint main(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int c;
- X
- X stdoutf = 0;
- X if (argc > 1)
- X stdoutf = 1;
- X
- X if (argc > 2) {
- X fprintf(stderr, "Usage: ... | hold filename\n");
- X fprintf(stderr, " or ... | hold > filename\n");
- X return(1);
- X }
- X#ifndef MSDOS
- X /* Trap signals to remove file on. */
- X signal(SIGHUP, Trap);
- X signal(SIGINT, Trap);
- X signal(SIGQUIT, Trap);
- X signal(SIGTERM, Trap);
- X#endif
- X if ((fp = fopen(mktemp(fname), "w")) == NULL)
- X errclean(2, "open %s", fname, 0);
- X
- X while ((c = getchar()) != EOF)
- X fputc(c, fp);
- X
- X if (ferror(stdin) || ferror(fp))
- X errclean(3, "copy stdin to %s", 0, fname);
- X
- X if (fclose(fp) != 0)
- X errclean(4, "close %s", fname, 0);
- X
- X if (stdoutf) {
- X if (rename(fname, argv[1]) != 0)
- X errclean(5, "rename %s to %s", fname, argv[1]);
- X }
- X else {
- X if ((fp = fopen(fname, "r")) == NULL)
- X errclean(6, "open %s", fname, 0);
- X
- X while ((c = getc(fp)) != EOF)
- X fputc(c, stdout);
- X
- X if (ferror(stdout) || ferror(fp))
- X errclean(7, "copy %s to stdout", 0, fname);
- X
- X if (fclose(fp) != 0)
- X errclean(8, "close %s", fname, 0);
- X
- X if (unlink(fname) != 0)
- X errclean(9, "remove %s", fname, 0);
- X }
- X
- X return(0);
- X}
- X
- X
- X#ifndef MSDOS
- Xint rename(s1, s2) /* s2 = new name, s1 = existing name */
- X char *s1, *s2;
- X{
- X /* assure that new name doesn't exist */
- X if (unlink(s2) != 0 && errno != ENOENT) {
- X errclean(10, "remove %s", s2, 0);
- X return(1);
- X }
- X /* connect new name to existing file */
- X if (link(s1, s2) != 0) {
- X errclean(11, "link %s to %s", s1, s2);
- X return(1);
- X }
- X /* remove old name for the file */
- X if (unlink(s1) != 0) {
- X errclean(12, "remove %s", s1, 0);
- X return(1);
- X }
- X return(0);
- X}
- X#endif
- X
- X/*
- X * errclean - output error message and exit to system
- X */
- Xerrclean(code, string, arg1, arg2)
- X int code;
- X char *string;
- X char *arg1, *arg2;
- X{
- X char lstr[80];
- X
- X if (fp != NULL) {
- X (void)unlink(fname);
- X fp = NULL;
- X }
- X sprintf(lstr, "hold %2d: can't %s\n", code, string);
- X fprintf(stderr, lstr, arg1, arg2);
- X exit(code);
- X}
- X
- END_OF_FILE
- if test 2960 -ne `wc -c <'hold.c'`; then
- echo shar: \"'hold.c'\" unpacked with wrong size!
- fi
- # end of 'hold.c'
- fi
- echo shar: End of shell archive.
- exit 0
-